import { Cell } from "@ui/pack-antv-x6";
import {get,set,camelCase, has} from "lodash-es"
import { IPackNifi } from "./inter";
import Nifi from "./nifi";
import { ElMessage } from "element-plus";
import {t} from "./i18n/index"

export const FlowKeys = ["processors","processGroups","inputPorts","outputPorts","funnels","labels","remoteProcessGroups","connections"];

export const deepKeys = (obj: any, pk?: string[]) => {
    if (obj != null && typeof obj === 'object') {
        const res: string[][] = [];
        const ks = Object.keys(obj);
        for (const k of ks) {
            const r = deepKeys(obj[k], pk ? [...pk, k] : [k]);
            res.push(...r)
        }
        return res;
    } else {
        return pk ? [pk] : [];
    }
}

export const deepObj = (obj: any, pk?: string[]) => {
    if (obj != null && typeof obj === 'object') {
        const res = new Map();
        const ks = Object.keys(obj);
        for (const k of ks) {
            const r = deepObj(obj[k], pk ? [...pk, k] : [k]);
            for (const [key, value] of r.entries()) {
                res.set(key, value)
            }
        }
        return res;
    } else {
        const res = new Map();
        pk && res.set(pk, obj)
        return res;
    }
}


export const diff = (target:any,source:any) => {
    const sp = '#$.$#';
    const tks = deepKeys(target).map(s => s.join(sp));
    const sks = deepKeys(source).map(s => s.join(sp));
    const ks = Array.from(new Set([...tks,...sks])).map(s => s.split(sp))
    const res:any = {};
    let bool = false;
    //
    for(const k of ks){
        const tv = get(target,k);
        const sv = get(source,k);
        //
        if(tv !== sv){
            const tk = k.slice(0,-1);
            const ttv = get(target,tk)
            if(has(target,k) && !Array.isArray(ttv)){
                set(res,k,tv);
            }
            else{
                set(res,tk,ttv)
            }
            bool = true;
        }
    }
    //
    return bool ? res : undefined;
}

export const getCamelName = (cell?:Cell) => {
    const name = cell ? cell.prop('name') : 'blank';
    return camelCase(name) as IPackNifi.NIFI_CAMEL_NAME
}

export const pickData = (data:any,keys:[k:string,s?:string|string[]|((d:any) => any)][],type:"object"|"array"|Object = "object") => {
    const res:any = typeof type === 'string' ? (type == 'array' ? [] : {}) : type;
    for(const [k,t = k] of keys){
        let v;
        if(typeof t == 'function'){v = t(data)}
        else if(Array.isArray(t)){
            const sk = t.filter(k => get(data,k))[0];
            sk && (v = get(data,sk))
        }
        else{
            v = get(data,t)
        }
        if(v != undefined){
            type == 'array' ? res.push([k,v]) : set(res,k,v);
        }
    }
    return res;
}

const NODELIST_KEYS:[key:string,sk?:any][] = [
    ['inputPort'],
    ['outputPort'],
    ['icon'],
    ['defaultRelations'],
    ['label'],
    ['type','startupClass'],
    ['desc','pluginDescribe'],
]

const DEFAULT_NODE_LIST = [
    {label:t('util-node-list-label'),children:[
        {  name: "process-groups", label: t('util-node-groups-label'),icon:"icon-base-group" },
        {  name: "input-ports", label: t('util-node-input-label'),icon:'icon-base-in' },
        {  name: "output-ports", label: t('util-node-output-label'),icon:'icon-base-out' },
        { name: "labels", label: t('util-node-labels-label'), shape: "vue-text",icon:'icon-base-label' },
        {  name: "funnels", label: t('util-node-funnels-label'),icon:"icon-base-funnel" },
        {  name: "templates", label: t('util-node-templates-label'),icon:"icon-base-temp" },
      ]}
]
export const initNodeList = async (nifi:Nifi) => {
    // const url = '/hanyun/datadevelop-stream/stream/pluginManage/getAllBasicPluginInfoByUserId';
    const url = '/nifi-api/flow/processor-types';
    let res:any
    try {
        res = await nifi.api.get(url);
    } catch (error) {
        ElMessage.error(t('util-node-list-get-failed',{error}));
        console.error(error)
        return false;
    }
    //
    // tree - 
    const tree = res.result || res.content || res.processorTypes || [];
    //
    const f = (list:any[]) => {
        const res:any[] = [];
        
        // for(const d of list){
        //     const obj:any = pickData(d,NODELIST_KEYS)
        //     if(d.children && d.children.length > 0){
        //         obj.children = f(d.children)
        //     }
        //     else if(obj.type == undefined){
        //         // 区分分组和算子的
        //         obj.children = [];
        //     }
        //     if(obj.type){
        //         obj.name = "processors";
        //     }
        //     res.push(obj)
        // }
        const g:any = {};
        for(const d of list){
            const {type} = d;
            const ts = type.split('.')
            const group = ts.at(-2);
            if(!group) continue;
            if(!g[group]){
                g[group] = {children:[],label:group}
            }
            d.label = ts.at(-1);
            d.desc = d.description;
            d.name = "processors"
            g[group].children.push(d)
        }

        return Object.values(g) as any;
    }
    
    const list = f(tree);
    nifi.nodelist.setList([...list,...DEFAULT_NODE_LIST])
}


export const trycall = async (f:() => Promise<any>,message = t('error')) => {
    try {
        return await f();
    } catch (error) {
        ElMessage.error(message + " : " + error)
        console.error(error)
        return error;
    }
}

// 时长转换 毫秒数转换为格式化的数字
export const transToTime = (n:number = 0) => {
    if(n <= 0) return 0;
    const v = Math.floor(n / 1000);
    let D = 0;
    let h = Math.floor(v / 3600);
    let m = Math.floor(v % 3600 / 60)
    let s = Math.floor(v % 3600 % 60 )
    let sss = n % 1000;
    if(h > 24) {
        D = Math.floor(h / 24);
        h = h % 24;
    }

    return `${D > 0 ? D + t('day') : ''}${h > 0 ? h + t('hour') : ''}${m > 0 ? m +  t('minute') : ''}${s > 0 ? s +  t('second') : ''} ${sss > 0 ? sss +  t('millisecond') : ''}`;
}